package services

import (
	"fmt"
	"go-tool/components"
	"go-tool/db/orm_iray_proxy"
	"gopkg.in/olivere/elastic.v5"
	"reflect"
	"strings"
	"sync"
	"time"
)

//任务构建日志
type JobConstructLog struct {
	Timestamp         time.Time `json:"@timestamp"`
	Ts                time.Time `json:"ts"`
	LogTopic          string    `json:"log_topic"`
	Msg               string    `json:"msg"`
	JobID             string    `json:"jobId"`
	Stat              string    `json:"stat"`
	ConstructIP       string    `json:"constructIp"`
	RenderType        int       `json:"renderType"`     //渲染类型
	StartTime         string    `json:"startTime"`      //任务构建开始时间
	StrInitEndTime    string    `json:"strInitEndTime"` //任务构建结束时间
	StrSwitchTime     string    `json:"strSwitchTime"`  //任务场景转换成功时间
	FinishTime        string    `json:"finishTime"`     //任务提交IrayServer成功时间
	TotalCostTime     int64     `json:"totalCostTime"`
	LoadModelCostTime int64     `json:"loadModelCostTime"`
	//构建加载时长
	LoadSolutionCostTime int64 `json:"loadSolutionCostTime"`
	//构建场景转换时长
	ConvertModelCostTime int64 `json:"convertModelCostTime"`
	//构建上传iray时长
	SubmitIrayCostTime int64 `json:"submitIrayCostTime"`
	CleanTaskCostTime  int64 `json:"cleanTaskCostTime"`
}

func (e *JobConstructLog) DbToLog(info orm_iray_proxy.JobInfo) *JobConstructLog {
	e = &JobConstructLog{
		Timestamp:            info.StrSubmitTime.Time.UTC(),
		Ts:                   info.StrSubmitTime.Time.Local(),
		LogTopic:             "cloud-rendering-stat",
		JobID:                info.JobId,
		RenderType:           info.RenderType,
		Stat:                 "constructJobStat",
		Msg:                  "constructJobStat",
		StartTime:            info.StrInitStartTime.Time.Local().Format("2006-01-02 15:04:05"),
		StrInitEndTime:       info.StrInitEndTime.Time.Local().Format("2006-01-02 15:04:05"),
		StrSwitchTime:        info.StrSwitchTime.Time.Local().Format("2006-01-02 15:04:05"),
		FinishTime:           info.StrSubmitTime.Time.Local().Format("2006-01-02 15:04:05"),
		TotalCostTime:        info.StrSubmitTime.Time.Local().Unix() - info.StrInitStartTime.Time.Unix(),
		LoadSolutionCostTime: info.StrInitEndTime.Time.Local().Unix() - info.StrInitStartTime.Time.Unix(),
		ConvertModelCostTime: info.StrSwitchTime.Time.Local().Unix() - info.StrInitEndTime.Time.Unix(),
		SubmitIrayCostTime:   info.StrSubmitTime.Time.Local().Unix() - info.StrSwitchTime.Time.Unix(),
		LoadModelCostTime:    0,
		CleanTaskCostTime:    0,
	}
	if index := strings.Index(info.ConstructIp.String, ":"); info.ConstructIp.Valid && index > 0 {
		e.ConstructIP = info.ConstructIp.String[0:index]
	}
	return e
}

func (e *JobConstructLog) InsertEs() (err error) {
	components.EsClient.Index = "cloud-rendering-stat-" + e.Timestamp.Local().Format("2006.01")
	components.EsClient.Type = "doc"
	put, err := components.EsClient.Push(e)
	if err != nil {
		fmt.Printf("Indexed tweet %s to index s%s, type %s\n", put.Id, put.Index, put.Type)
		panic(err)
	}
	return
}

func (e *JobConstructLog) Each(startTime string, endTime string) (count int) {
	var wg sync.WaitGroup
	var lock sync.Mutex
	offset := 0
	DbJob := orm_iray_proxy.JobInfo{}
	minId, maxId := DbJob.QueryConstructResultMinIdAndMaxIdByTime(startTime, endTime)
	fmt.Printf("start joblog, id: %v - %v \n", minId, maxId)
	limit := 5000
	obj := JobConstructLog{}
	for {
		fmt.Println("db start")
		rows, err := DbJob.QueryByConstructResult(minId, maxId, int64(offset), int64(limit))
		wg.Wait()
		fmt.Println("start job construct log, offset: ", offset)
		if err != nil {
			fmt.Println("err: ", err)
			return
		}
		if len(rows) == 0 {
			fmt.Println("rows len : ", len(rows))
			return
		}
		wg.Add(1)
		go func(rows []orm_iray_proxy.JobInfo) {
			for i := 0; i < len(rows); i++ {
				lock.Lock()
				rows[i].SetRenderTypeByJobId()
				err = obj.DbToLog(rows[i]).InsertEs()
				if err != nil {
					fmt.Println("err: ", err)
					return
				}
				count++
				if count%100 == 0 {
					fmt.Println("count: ", count)
				}
				lock.Unlock()
			}
			wg.Done()
		}(rows)
		offset = offset + limit
	}
	return
}

func (e *JobConstructLog) EachEs() (count int) {
	components.EsClient.Index = "job"
	components.EsClient.Type = "log"
	//640781
	max := 2
	offset := 100
	limit := 10000
	for {
		q := elastic.NewQueryStringQuery("stat:constructJobStat")
		searchResult, err := components.EsClient.Search(q, offset, limit)
		fmt.Println(err)
		return
		if err != nil || len(searchResult.Hits.Hits) == 0 {
			fmt.Println(err)
			return
		}

		var obj JobConstructLog
		for _, item := range searchResult.Each(reflect.TypeOf(obj)) {
			t := item.(JobConstructLog)
			t.Ts = t.Timestamp.Local()
			t.LogTopic = "cloud-rendering-stat"
			t.Msg = t.Stat
			err = t.InsertPrdEs()
			if err != nil {
				fmt.Println(err)
			}
			count++
			if count%1000 == 0 {
				fmt.Println("count: ", count)
			}
		}
		offset = offset + limit
		if offset > max {
			return
		}
	}
	return
}

func (e *JobConstructLog) InsertPrdEs() (err error) {
	components.EsClientPrd.Index = "cloud-rendering-stat-" + e.Timestamp.Local().Format("2006.01")
	components.EsClientPrd.Type = "doc"
	put, err := components.EsClientPrd.Push(e)
	if err != nil {
		fmt.Printf("Indexed tweet %s to index s%s, type %s\n", put.Id, put.Index, put.Type)
		panic(err)
	}
	return
}
